// <editor-fold defaultstate="collapsed" desc="GNU GPLv3 Header">
/*
 * File:   AlawDecoder.java
 *
 * Copyright (C) 2013 Robert Antoni Buj Gelonch <rbuj@uoc.edu>
 * Copyright (C) 2013 David Megias Jimenez <dmegias@uoc.edu>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
// </editor-fold>
package uoc.libcompression.G711;

/**
 * G711 A-Law Encoder.
 *
 * @author Robert Antoni Buj Gelonch <rbuj@uoc.edu>
 * @version 1.0
 * @since 2013-08-24
 */
public final class AlawEncoder extends Alaw implements Encoder {

    /**
     *
     */
    public AlawEncoder() {
    }

    /**
     * Compress an audio data sample.
     *
     * @param sample 13-bit signed linear audio sample,
     * right–justified PCM, sign–extended to 16–bits.
     * @return The compressed data sample.
     */
    public byte compress(short sample) {
        int aux = Math.abs(sample);
        if (aux > 0x0FFF) {
            throw new UnsupportedOperationException("Only signed "
                    + "13–bit samples.");
        }
        byte exponent = (byte) aLawCompressTable[(aux >> 5) & 0x7F];
        byte mantissa;
        if (exponent == 0) {
            mantissa = (byte) ((aux >> (exponent + 1)) & 0x0F);
        } else {
            mantissa = (byte) ((aux >> (exponent)) & 0x0F);
        }
        byte res = (byte) (((exponent << 4) | mantissa) & 0x7F);
        if (Math.signum(sample) != -1) {
            return res;
        } else {
            return (byte) (0x80 | res);
        }
    }

    /**
     * Compress an audio data sample for transmition.
     * <p>
     * Bitwise exclusive OR between Clock 0101:0101 (0x55) and
     * compressed byte.
     *
     * @param sample PCM audio data.
     * @return The compressed audio sample ready for the transmission.
     */
    public byte compressTransmission(short sample) {
        return (byte) (compress(sample) ^ 0x55);
    }
}
